﻿#include "httppost.h"
#include <QByteArray>
#include <QCryptographicHash>
#include <QHttpMultiPart>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QObject>
#include <QTimer>
#include <QUrl>
#include "confsettings.h"
#include "globaltools.h"
#include "httpget.h"

void post(const QUrl &url, const QByteArray &data, QObject *context, std::function<void(QNetworkReply*)> callback, int timeout)
{
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1Literal("application/x-www-form-urlencoded"));
    QNetworkReply* reply = manager().post(request, data);
    if(reply)
    {
        if(callback)
            QObject::connect(reply, &QNetworkReply::finished, reply, [reply, callback](){
                callback(reply);
            });
        QObject::connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
        if(context)
            reply->setParent(context);
        if(timeout > 0)
            QTimer::singleShot(timeout, reply, SLOT(abort()));
    }
    else if(callback)
        callback(Q_NULLPTR);
}

void postJson(const QUrl &url, const QByteArray &data, QObject *receiver, const char *member, int timeout)
{
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1Literal("application/json"));
    QNetworkReply* reply = manager().post(request, data);
    if(reply)
    {
        if(receiver && member)
            QObject::connect(reply, SIGNAL(finished()), receiver, member);
        QObject::connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
        if(receiver)
            reply->setParent(receiver);
        if(timeout > 0)
            QTimer::singleShot(timeout, reply, SLOT(abort()));
    }
    else if(receiver && member)
        QMetaObject::invokeMethod(receiver, member);
}

QByteArray getFileName(const QByteArray &data, const QByteArray &suffix)
{
    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(data);
    QByteArray md5 = hash.result().toHex();
    if(md5.isEmpty())
        return QByteArray();
    return md5+suffix;
}

void upload(const QByteArray &data, const QByteArray &fileName, QObject* context, std::function<void (const QString *)> callback, int timeout)
{
#ifndef ONLY_SHOW_CHAT
    if(fileName.isEmpty() || ConfSettings::instance()->httpServer.isEmpty())
    {
        if(callback)
            callback(Q_NULLPTR);
    }
#endif
#ifndef ONLY_SHOW_CHAT
    QNetworkRequest request(ConfSettings::instance()->httpServer);

    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QHttpPart part;
    part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
    part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\""+fileName+"\""));
    part.setBody(data);
    multiPart->append(part);

    QNetworkReply* reply = manager().post(request, multiPart);
    if(reply)
    {
        multiPart->setParent(reply);
        if(callback)
            QObject::connect(reply, &QNetworkReply::finished, reply, [reply, callback](){
                if(reply->isFinished() && reply->error() == QNetworkReply::NoError)
                {
                    auto read = reply->readAll();
                    log_debug() << read;
                    QJsonDocument doc = QJsonDocument::fromJson(read);
                    if(doc.isObject())
                    {
                        QJsonObject json = doc.object();
                        auto vList = json.value(QLatin1String("obj")).toArray();
                        if(!vList.isEmpty())
                        {
                            auto first = vList.first();
                            if(first.isObject())
                            {
                                auto storeUrl = first.toObject().value(QLatin1String("storeUrl"));
                                if(storeUrl.isString())
                                {
                                    QString url = storeUrl.toString();
                                    callback(&url);
                                    return;
                                }
                            }
                        }
                    }
                }
                callback(Q_NULLPTR);
            });
        QObject::connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
        if(context)
            reply->setParent(context);
        if(timeout > 0)
            QTimer::singleShot(timeout, reply, SLOT(abort()));
    }
    else
    {
        multiPart->deleteLater();
        if(callback)
            callback(Q_NULLPTR);
    }
#endif
}
